<?php
/**
 * Created by PhpStorm.
 * User: 12133
 * Date: 2025/4/30
 * Time: 15:24
 */

namespace app\service;


class WeixinQrcode
{
    private $appid;
    private $secret;
    private $accessTokenUrl = 'https://api.weixin.qq.com/cgi-bin/token';
    private $wxacodeUrl = 'https://api.weixin.qq.com/wxa/getwxacode';

    public function __construct($appid, $secret) {
        $this->appid = $appid;
        $this->secret = $secret;
    }

    /**
     * 生成小程序二维码
     * @param string $code 业务参数
     * @param string $savePath 保存路径（可选）
     * @return array|string 返回图片路径或base64
     */
    public function generateQRCode($code, $savePath = null) {
        try {
            // 1. 获取Access Token
            $accessToken = $this->getAccessToken();

            // 2. 构造请求参数
            $params = [
                'path' => 'pages/user/apply?code=' . urlencode($this->encryptCode($code)),
                'width' => 430,
                'auto_color' => false,
                'line_color' => ['r' => 0, 'g' => 0, 'b' => 0],
                'is_hyaline' => true
            ];

            // 3. 请求微信接口
            $imageData = $this->httpPost($this->wxacodeUrl . '?access_token=' . $accessToken, json_encode($params));

            // 4. 处理返回结果
            if (strpos($imageData, 'errcode')) {
                $error = json_decode($imageData, true);
                throw new Exception("微信接口错误：{$error['errmsg']}", $error['errcode']);
            }

            // 5. 保存或返回图片
            if ($savePath) {
                $filename = 'qrcode_' . md5($code) . '.png';
                file_put_contents($savePath . $filename, $imageData);
                return $filename;
            } else {
                return 'data:image/png;base64,' . base64_encode($imageData);
            }

        } catch (Exception $e) {
            error_log("生成二维码失败: " . $e->getMessage());
            return ['error' => $e->getMessage()];
        }
    }

    /**
     * 获取Access Token
     */
    private function getAccessToken() {
        $params = [
            'grant_type' => 'client_credential',
            'appid' => $this->appid,
            'secret' => $this->secret
        ];

        $response = $this->httpGet($this->accessTokenUrl, $params);
        $data = json_decode($response, true);

        if (isset($data['access_token'])) {
            return $data['access_token'];
        } else {
            throw new Exception("获取Access Token失败: " . ($data['errmsg'] ?? '未知错误'));
        }
    }

    /**
     * 参数加密（AES-128-CBC）
     */
    private function encryptCode($code) {
        $key = 'your_encryption_key'; // 32字符
        $iv = substr($key, 0, 16);
        return openssl_encrypt($code, 'AES-128-CBC', $key, 0, $iv);
    }

    /**
     * HTTP GET请求
     */
    private function httpGet($url, $params) {
        $url .= '?' . http_build_query($params);
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }

    /**
     * HTTP POST请求
     */
    private function httpPost($url, $data) {
        $ch = curl_init($url);
        curl_setopt_array($ch, [
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $data,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_SSL_VERIFYPEER => false,
            CURLOPT_HTTPHEADER => ['Content-Type: application/json']
        ]);
        $response = curl_exec($ch);
        curl_close($ch);
        return $response;
    }
}